/*
 *
 * *******************************************************************
 *   @项目名称: BHex Android
 *   @文件名称: SymbolDataManager.java
 *   @Date: 11/29/18 3:21 PM
 *   @Author: chenjun
 *   @Copyright（C）: 2018 BlueHelix Inc.   All rights reserved.
 *   注意：本内容仅限于内部传阅，禁止外泄以及用于其他的商业目的.
 *  *******************************************************************
 *
 */

package io.bhex.sdk.data_manager;

import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.text.TextUtils;

import com.google.gson.Gson;
import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;
import com.tencent.mmkv.MMKV;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Timer;
import java.util.TimerTask;

import io.bhex.baselib.constant.AppData;
import io.bhex.baselib.core.SPEx;
import io.bhex.baselib.network.BParamsBuilder;
import io.bhex.baselib.network.HttpUtils;
import io.bhex.baselib.network.Utils.CodeUtils;
import io.bhex.baselib.network.Utils.Convert;
import io.bhex.baselib.network.listener.SimpleResponseListener;
import io.bhex.baselib.network.params.GetParams;
import io.bhex.baselib.network.params.PostParams;
import io.bhex.baselib.network.response.ResponseListener;
import io.bhex.baselib.utils.DebugLog;
import io.bhex.baselib.utils.JsonConvertor;
import io.bhex.baselib.utils.JsonUtils;
import io.bhex.baselib.utils.NumberUtils;
import io.bhex.baselib.utils.SignUtils;
import io.bhex.sdk.BhexSdk;
import io.bhex.sdk.Config;
import io.bhex.sdk.Urls;
import io.bhex.sdk.account.UserInfo;
import io.bhex.sdk.config.BackupDomainResponse;
import io.bhex.sdk.config.ConfigApi;
import io.bhex.sdk.config.bean.BackupDomainList;
import io.bhex.sdk.config.domain.BackupDomainManager;
import io.bhex.sdk.enums.COIN_TYPE;
import io.bhex.sdk.quote.bean.ChainType;
import io.bhex.sdk.quote.bean.CoinPairBean;
import io.bhex.sdk.quote.bean.FavoriteListResponse;
import io.bhex.sdk.quote.bean.NewCoinPairListBean;
import io.bhex.sdk.quote.bean.OptionCategoryBean;
import io.bhex.sdk.quote.bean.QuoteTokensBean;

public class SymbolDataManager {
    private static SymbolDataManager mInstance;
    private MMKV mmkvSymbols;
    //private QuoteTokensBean mQuoteTokensBean;
    //private CoinPairListBean mCoinPairListBean;
    private NewCoinPairListBean mNewCoinPairListBean;
    private Handler mHandler;
    private HashMap<String, CoinPairBean> symbolMap = new HashMap<>();
    private HashMap<String, QuoteTokensBean.TokenItem> tokenMap = new HashMap<>();
    private HashMap<String, Integer> symbolDigitMap = new HashMap<>();
    private HashMap<String, CoinPairBean> optionSymbolMap = new HashMap<>();
    private HashMap<String, Integer> optionSymbolDigitMap = new HashMap<>();
    private HashMap<String, CoinPairBean> futuresSymbolMap = new HashMap<>();
    private HashMap<String, Integer> futuresSymbolDigitMap = new HashMap<>();
    private HashMap<String, OptionCategoryBean> optionCategoryMap = new HashMap<>();
    private List<LoginstatusChange> mObserverList = new ArrayList<>();
    private List<OptionSymbolsChange> mOptionSymbolsChangeList = new ArrayList<>();
    private List<FuturesSymbolsChange> mFuturesSymbolsChangeList = new ArrayList<>();


    private SharedPreferences mPrefs;
    public static final String PREFERENCE_SYMBOLS = "symbols";
    public static final String PREFERENCE_QUOTETOKENS = "quoteTokens";
    public static final String PREFERENCE_NEW_SYMBOLS = "newSymbols";
    //private boolean bCacheSymbols = true;
    //private boolean bCacheTokens = true;
    private boolean bCacheNewSymbols = true;
    private Timer timer;
    private TimerTask task;
    private static final int nPeriod = 60 * 1000 * 3;   //3分钟
    private static final int SYMBOLS_MESSAGE = 0X1;
    private static final int QUOTETOKENS_MESSAGE = 0X2;
    private static final int NEWSYMBOLS_MESSAGE = 0X3;
    private static final int REQUEST_BACKUP_DOMAIN = 0X4;

    private CoinPairBean mDefaultBBTradeCoinPair;
    private CoinPairBean mDefaultOptionTradeCoinPair;
    private CoinPairBean mDefaultFuturesTradeCoinPair;
    private String orgId = "";

    public interface LoginstatusChange{
        void onFavriateChange();

    }

    public interface OptionSymbolsChange{
        void onOptionSymbolsChange();

    }

    public interface FuturesSymbolsChange{
        void onFuturesSymbolsChange();

    }
    //自选列表 TODO 注意：Map 的 key = exchangeId + symbolId
    public Map<String,FavoriteListResponse.FavoriteBean> favoritesMap = new HashMap<>();

    public static SymbolDataManager GetInstance() {
        if (mInstance == null)
            mInstance = new SymbolDataManager();

        return mInstance;
    }

    private SymbolDataManager() {
        mmkvSymbols = MMKV.mmkvWithID("APP_SYMBOLS");
        mHandler = new Handler(Looper.getMainLooper()){
            @Override
            public void handleMessage(Message msg) {
                super.handleMessage(msg);
                switch (msg.what){
                    /*case QUOTETOKENS_MESSAGE:
                        getQuoteTokens((ResponseListener)msg.obj);
                        break;
                    case SYMBOLS_MESSAGE:
                        getCoinPairList((ResponseListener)msg.obj);*/
                    case NEWSYMBOLS_MESSAGE:
                        getNewCoinPairList((ResponseListener)msg.obj);
                        break;
                    case REQUEST_BACKUP_DOMAIN:
                        requestBackupDomainJson();
                        break;
                }
            }
        };

    }

    /**
     * 请求备用域名Json配置文件方案
     */
    private void requestBackupDomainJson() {
        Config config = BhexSdk.getConfig();
        if (config == null) {
            return;
        }
        String domainReqUrl = config.getDomainReqUrl();
        if (TextUtils.isEmpty(domainReqUrl)) {
            return;
        }
        ConfigApi.requestBackupDomain(domainReqUrl,new SimpleResponseListener<BackupDomainResponse>(){
            @Override
            public void onFinish() {
                super.onFinish();
            }

            @Override
            public void onSuccess(BackupDomainResponse response) {
                super.onSuccess(response);
                if (CodeUtils.isSuccess(response)) {
                    String domainsStr = response.getDomains();
                    loadBackupDomains(response.getOrgId(),response.getResponseRandomKey(),domainsStr);
                }
            }

            @Override
            public void onError(Throwable error) {
                super.onError(error);
            }
        });
    }

    public void Init(){

        try {
            //1. 加载Config币对列表本地缓存数据
            String newSymbolsString = mmkvSymbols.decodeString(PREFERENCE_NEW_SYMBOLS , "");
            if (!newSymbolsString.isEmpty()) {
                Gson gson = new Gson();
                NewCoinPairListBean cacheConfigData = gson.fromJson(newSymbolsString, new TypeToken<NewCoinPairListBean>() {
                }.getType());
                if (cacheConfigData != null) {
                    mNewCoinPairListBean = cacheConfigData;
                    //赋值orgId
                    orgId = mNewCoinPairListBean.orgId;
                    //设置默认币币交易币对
                    if(mDefaultBBTradeCoinPair == null && mNewCoinPairListBean.symbol != null && mNewCoinPairListBean.symbol.size()>0){
                        for (CoinPairBean coinPairBean : mNewCoinPairListBean.symbol) {
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_BB.getCoinType());
                        }
                        mDefaultBBTradeCoinPair = mNewCoinPairListBean.symbol.get(0);
                    }
                    //设置默认期权交易币对
                    if(mDefaultOptionTradeCoinPair == null && mNewCoinPairListBean.optionSymbol != null && mNewCoinPairListBean.optionSymbol.size()>0){
                        for (CoinPairBean coinPairBean : mNewCoinPairListBean.optionSymbol) {
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_OPTION.getCoinType());
                        }
                        mDefaultOptionTradeCoinPair = mNewCoinPairListBean.optionSymbol.get(0);
                    }
                    //设置默认合约交易币对
                    if(mDefaultFuturesTradeCoinPair == null && mNewCoinPairListBean.futuresSymbol != null && mNewCoinPairListBean.futuresSymbol.size()>0) {
                        for (CoinPairBean coinPairBean : mNewCoinPairListBean.futuresSymbol) {
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_PERPETUAL_CONTRACT.getCoinType());
                        }
                        //设置默认交易币种 期货
                        mDefaultFuturesTradeCoinPair = mNewCoinPairListBean.futuresSymbol.get(0);
                    }

                    //加载币对列表到内存中
                    loadSymbolsToMap(mNewCoinPairListBean);
                    //加载token到内存中
                    loadTokenItemToMap(mNewCoinPairListBean);
                }
            }
        } catch (JsonSyntaxException e) {
            e.printStackTrace();
        }

        timer = new Timer();
        task = new TimerTask() {
            @Override
            public void run() {
                //mHandler.sendEmptyMessage(QUOTETOKENS_MESSAGE);
                //mHandler.sendEmptyMessage(SYMBOLS_MESSAGE);
                mHandler.sendEmptyMessage(NEWSYMBOLS_MESSAGE);
            }
        };

        timer.schedule(task, 0,  nPeriod);

        if (UserInfo.isLogin()) {
            //登录了获取自选
            SymbolDataManager.GetInstance().getFavorites();
        }
    }

    public void release() {
        if (task != null) {
            task.cancel();
        }
        if (timer != null) {
            timer.purge();
            timer.cancel();
        }
        mInstance = null;
    }

    /*private void saveQuoteTokensToNative(QuoteTokensBean response) {
        if (response != null) {
            try {
                SharedPreferences.Editor prefEditor = mPrefs.edit();

                Gson gson = new Gson();
                String gsonString = gson.toJson(response, new TypeToken<QuoteTokensBean>() {
                }.getType());
                if (gsonString != null && !"".equals(gsonString)) {
                    prefEditor.putString(PREFERENCE_QUOTETOKENS, gsonString);
                    prefEditor.commit();
                    prefEditor.apply();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    private void saveSymbolsToNative(CoinPairListBean response) {
        if (response != null) {
            try {
                SharedPreferences.Editor prefEditor = mPrefs.edit();

                Gson gson = new Gson();
                String gsonString = gson.toJson(response, new TypeToken<CoinPairListBean>() {
                }.getType());
                if (gsonString != null && !"".equals(gsonString)) {
                    prefEditor.putString(PREFERENCE_SYMBOLS, gsonString);
                    prefEditor.commit();
                    prefEditor.apply();
                }

            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }*/

    /**
     * 保存币种到本地
     * @param response
     */
    private void saveNewSymbolsToNative(NewCoinPairListBean response) {
        try {
            if (response != null) {
                Gson gson = new Gson();
                String gsonString = gson.toJson(response, new TypeToken<NewCoinPairListBean>() {}.getType());
                if (gsonString != null && !"".equals(gsonString)) {
                    mmkvSymbols.encode(PREFERENCE_NEW_SYMBOLS, gsonString);
                    //判断coin是否在 futuresSymbol中
                    //resetContractTradeCoinValue(response.futuresSymbol);
                    //判断coin是否在 futuresSymbol中
                    //resetOptionTradeCoinValue(response.optionSymbol);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    //改写已存储的CoinPairBean 多语言适配
    public void resetContractTradeCoinValue(List<CoinPairBean> futuresSymbol){

        String tradeCoin = SPEx.get("contractTradeCoin", "");
        if(TextUtils.isEmpty(tradeCoin)){
            return;
        }

        CoinPairBean coin = Convert.fromJson(tradeCoin, CoinPairBean.class);

        for(int i=0;i<futuresSymbol.size();i++){
            CoinPairBean item = futuresSymbol.get(i);
            if(item.isEquals(coin)){
                //保存信息
                String coinJson = Convert.toJson(item);
                DebugLog.d("ABBB====>","coin_json=="+coinJson);
                //LongLog.loge("ABBB====>",);
                SPEx.set("contractTradeCoin", coinJson);

                return;
            }
        }
    }


    //改写已存储的CoinPairBean 多语言适配
    public void resetOptionTradeCoinValue(List<CoinPairBean> futuresSymbol){

        String tradeCoin = SPEx.get("optionTradeCoin", "");
        if(TextUtils.isEmpty(tradeCoin)){
            return;
        }

        CoinPairBean coin = Convert.fromJson(tradeCoin, CoinPairBean.class);

        for(int i=0;i<futuresSymbol.size();i++){
            CoinPairBean item = futuresSymbol.get(i);
            if(item.isEquals(coin)){
                //保存信息
                String coinJson = Convert.toJson(item);
                DebugLog.d("ABBB====>","coin_json=="+coinJson);
                //LongLog.loge("ABBB====>",);
                SPEx.set("contractTradeCoin", coinJson);

                return;
            }
        }
    }


    public void setLoginChangeObserver(LoginstatusChange observer){
        if(observer != null)
            mObserverList.add(observer);
    }

    public void setOptionSymbolsChangeObserver(OptionSymbolsChange observer){
        if(observer != null)
            mOptionSymbolsChangeList.add(observer);
    }

    //设置合约币种变化监听
    public void setFuturesSymbolsChangeObserver(FuturesSymbolsChange observer){
        if(observer != null)
            mFuturesSymbolsChangeList.add(observer);
    }

/*    public void getQuoteTokens(final ResponseListener listener) {
        if (mNewCoinPairListBean != null && mNewCoinPairListBean.quoteToken != null && listener != null) {
            listener.onSuccess(mNewCoinPairListBean.quoteToken);
            if(bCacheNewSymbols == false)
                return;
        }

        getNewCoinPairList(new SimpleResponseListener<NewCoinPairListBean>(){
            @Override
            public void onFinish() {
                super.onFinish();
                if (listener != null)
                    listener.onFinish();
            }

            @Override
            public void onSuccess(NewCoinPairListBean response) {
                super.onSuccess(response);
                if (listener != null)
                    listener.onSuccess(response.quoteToken);

            }
        });

        *//*if (mQuoteTokensBean != null && listener != null) {
            listener.onSuccess(mQuoteTokensBean);
            if(bCacheTokens == false)
                return;
        }
        GetParams params = BParamsBuilder.get()
                .url(Urls.API_QUOTE_TOKEN_LIST_URL)
                .build();
        HttpUtils.getInstance().request(params, QuoteTokensBean.class, new SimpleResponseListener<QuoteTokensBean>() {
            @Override
            public void onBefore() {
                super.onBefore();
                if (listener != null)
                    listener.onBefore();
            }

            @Override
            public void onFinish() {
                super.onFinish();
                if (listener != null)
                    listener.onFinish();
            }

            @Override
            public void onSuccess(QuoteTokensBean response) {
                super.onSuccess(response);
                if (CodeUtils.isSuccess(response, true)) {
                    if(listener != null ) {
                        listener.onSuccess(response);
                    }
                    bCacheTokens = false;
                    saveQuoteTokensToNative(response);
                    mQuoteTokensBean = response;
                }
            }

            @Override
            public void onError(Throwable error) {
                super.onError(error);

                Message sendMessage = new Message();
                sendMessage.what = QUOTETOKENS_MESSAGE;
                sendMessage.obj = listener;
                mHandler.removeMessages(QUOTETOKENS_MESSAGE);
                mHandler.sendMessageDelayed(sendMessage, AppData.Config.TIMER_PERIOD_DEFAULT_VALUE);
            }
        });*//*
    }


    *//**
     * 获取币对列表
     *//*
    public void getCoinPairList(final ResponseListener listener) {

        if (mNewCoinPairListBean != null && mNewCoinPairListBean.symbol != null && listener != null) {
            listener.onSuccess(mNewCoinPairListBean.symbol);
            if(bCacheNewSymbols == false)
                return;
        }

        getNewCoinPairList(new SimpleResponseListener<NewCoinPairListBean>(){
            @Override
            public void onFinish() {
                super.onFinish();
                if (listener != null)
                    listener.onFinish();
            }

            @Override
            public void onSuccess(NewCoinPairListBean response) {
                super.onSuccess(response);
                if (listener != null)
                    listener.onSuccess(response.symbol);

            }
        });

    }*/

    /**
     * 获取币币作价单位的token id list
     * @return
     */
    public List<String> getQuoteCoinList(){
        List<String> tokenList = new ArrayList<>();
        List<QuoteTokensBean.TokenItem> quoteTokenList = getQuoteTokenList();
        if (quoteTokenList != null) {
            for (QuoteTokensBean.TokenItem tokenItem : quoteTokenList) {
                if (tokenItem != null) {
                    String tokenId = tokenItem.getTokenId();
                    if (!TextUtils.isEmpty(tokenId)) {
                        tokenList.add(tokenId);
                    }
                }
            }
        }

        return tokenList;
    }

    /**
     * 获取币币token的token id list
     * @return
     */
    public List<String> getBBTokensList(){
        List<String> tokenList = new ArrayList<>();
        List<QuoteTokensBean.TokenItem> quoteTokenList = getTokenList();
        if (quoteTokenList != null) {
            for (QuoteTokensBean.TokenItem tokenItem : quoteTokenList) {
                if (tokenItem != null) {
                    String tokenId = tokenItem.getTokenId();
                    if (!TextUtils.isEmpty(tokenId)) {
                        tokenList.add(tokenId);
                    }
                }
            }
        }

        return tokenList;
    }

    public List<QuoteTokensBean.TokenItem> getQuoteTokenList(){
        if (mNewCoinPairListBean != null && mNewCoinPairListBean.quoteToken != null ) {
            return mNewCoinPairListBean.quoteToken;
        }
        else
            return null;

    }

    public List<QuoteTokensBean.TokenItem> getTokenList(){
        if (mNewCoinPairListBean != null && mNewCoinPairListBean.token != null ) {
            return mNewCoinPairListBean.token;
        }
        else
            return null;

    }

    public QuoteTokensBean.TokenItem getToken(String tokenId){
        if (tokenId != null && mNewCoinPairListBean != null && mNewCoinPairListBean.token != null ) {
            for (QuoteTokensBean.TokenItem tokenItem : mNewCoinPairListBean.token){
                if(tokenItem != null){
                    if(tokenId.equalsIgnoreCase(tokenItem.getTokenId()))
                        return tokenItem;
                }
            }
        }
        return null;
    }

    /**
     * 获取期权板分类信息
     * @return
     */
    public List<OptionCategoryBean> getOptionCategoryList(){
        if (mNewCoinPairListBean != null) {
            List<OptionCategoryBean> optionCategoryList = mNewCoinPairListBean.optionUnderlying;
            return optionCategoryList;
        }
        return null;
    }

    /**
     * 获取期权板分类信息
     * @return
     */
    public HashMap<String,OptionCategoryBean> getOptionCategoryMap(){
        return optionCategoryMap;
    }

    /**
     * 根据分类id获取期权板信息
     * @param boardId
     * @return
     */
    public OptionCategoryBean getOptionCategoryMap(String boardId){
        OptionCategoryBean optionCategoryBean = optionCategoryMap.get(boardId);
        return optionCategoryBean;
    }

    /**
     * 获取Config币对列表
     */
    public void getNewCoinPairList(final ResponseListener listener) {

        if (mNewCoinPairListBean != null && listener != null) {
            //handler循环更新 listener是空，不走此处，不会直接回调数据
            listener.onSuccess(mNewCoinPairListBean);
            if(bCacheNewSymbols == false)
                return;
        }

        GetParams params = BParamsBuilder.get()
                .url(Urls.API_NEW_SYMBOLS)
                .addParam("type","all")
                .addParam("without_country","true")
                .build();
        HttpUtils.getInstance().request(params, NewCoinPairListBean.class, new SimpleResponseListener<NewCoinPairListBean>() {
            @Override
            public void onFinish() {
                super.onFinish();
                if (listener != null)
                    listener.onFinish();
            }

            @Override
            public void onSuccess(NewCoinPairListBean response) { super.onSuccess(response);
                if (CodeUtils.isSuccess(response, true)) {
                    orgId = response.orgId;
                    /**添加一下自选配置*********/
                    List<CoinPairBean> bbSymbolsList = response.symbol;
                    //DebugLog.d("ABBB====>","json=="+ JsonUtils.toJson(bbSymbolsList));
                    //LongLog.loge("ABBB====>","json=="+ JsonUtils.toJson(bbSymbolsList));
                    if (bbSymbolsList != null && favoritesMap.size()>0) {
                        DebugLog.e("ZIXUAN","=============================");
                        for (CoinPairBean bbSymbol : bbSymbolsList) {
                            //循环设置币种类型为币币
                            bbSymbol.setCoinType(COIN_TYPE.COIN_TYPE_BB.getCoinType());
                            //自选处理
                            String customKeyOfFavorite = bbSymbol.getExchangeId() + "." + bbSymbol.getSymbolId();
                            if (favoritesMap.containsKey(customKeyOfFavorite)) {
                                bbSymbol.setFavorite(true);
                                DebugLog.e("ZIXUAN","== "+customKeyOfFavorite);
                            }
                        }
                    }
                    /** 处理币对数据-对应设置币对类型 和 默认交易币种 ********************/
                    if(mDefaultBBTradeCoinPair == null && response.symbol != null && response.symbol.size()>0) {
                        for (CoinPairBean coinPairBean : response.symbol) {
                            //统一设置币币列表--币种类型
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_BB.getCoinType());
                        }
                        //币币-设置默认交易币种
                        mDefaultBBTradeCoinPair = response.symbol.get(0);
                    }
                    if(mDefaultOptionTradeCoinPair == null && response.optionSymbol != null && response.optionSymbol.size()>0) {
                        for (CoinPairBean coinPairBean : response.optionSymbol) {
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_OPTION.getCoinType());
                        }
                        //期权-设置默认交易币种
                        mDefaultOptionTradeCoinPair = response.optionSymbol.get(0);
                    }
                    if(mDefaultFuturesTradeCoinPair == null && response.futuresSymbol != null && response.futuresSymbol.size()>0) {
                        for (CoinPairBean coinPairBean : response.futuresSymbol) {
                            coinPairBean.setCoinType(COIN_TYPE.COIN_TYPE_PERPETUAL_CONTRACT.getCoinType());
                        }
                        //期货-设置默认交易币种
                        mDefaultFuturesTradeCoinPair = response.futuresSymbol.get(0);
                    }

                    //回调结果
                    if(listener != null){
                        listener.onSuccess(response);
                    }

                    //缓存币对到本地
                    saveNewSymbolsToNative(response);

                    //加载币对列表到内存中
                    loadSymbolsToMap(response);
                    //加载token到内存中
                    loadTokenItemToMap(response);

                    mNewCoinPairListBean = response;

                    //期权-币种有变化，提示币种变化
                    if(mNewCoinPairListBean != null && mNewCoinPairListBean.optionSymbol != null &&
                            !getSymbolsListStr(mNewCoinPairListBean.optionSymbol).equalsIgnoreCase(getSymbolsListStr(response.optionSymbol))) {
                        if (mOptionSymbolsChangeList != null && mOptionSymbolsChangeList.size() > 0) {
                            for (OptionSymbolsChange observer : mOptionSymbolsChangeList) {
                                observer.onOptionSymbolsChange();
                            }
                        }
                    }
                    //期货-币种有变化，提示币种变化
                    if(mNewCoinPairListBean != null && mNewCoinPairListBean.futuresSymbol != null &&
                            !getSymbolsListStr(mNewCoinPairListBean.futuresSymbol).equalsIgnoreCase(getSymbolsListStr(response.futuresSymbol))) {
                        if (mFuturesSymbolsChangeList != null && mFuturesSymbolsChangeList.size() > 0) {
                            for (FuturesSymbolsChange observer : mFuturesSymbolsChangeList) {
                                observer.onFuturesSymbolsChange();
                            }
                        }
                    }

                    bCacheNewSymbols = false;

                    loadBackupDomains(response.orgId,response.responseRandomKey,response.domains);

                }
            }

            @Override
            public void onError(Throwable error) {
                super.onError(error);
                //接口失败了，重新获取
                Message sendMessage = new Message();
                sendMessage.what = NEWSYMBOLS_MESSAGE;
                sendMessage.obj = listener;
                //mHandler.removeMessages(SYMBOLS_MESSAGE);
                mHandler.sendMessageDelayed(sendMessage, AppData.Config.TIMER_PERIOD_DEFAULT_VALUE);
                mHandler.sendEmptyMessageDelayed(REQUEST_BACKUP_DOMAIN,2000);
            }

        });

    }

    /**
     * 更新域名换成列表
     * @param orgId
     * @param responseRandomKey
     * @param domains
     */
    private void loadBackupDomains(String orgId, String responseRandomKey, String domains) {
        try {
            Config config = BhexSdk.getConfig();
            if (TextUtils.isEmpty(orgId)) {
                if (config != null) {
                    orgId = config.getOrdId();
                }
            }
            if (TextUtils.isEmpty(responseRandomKey)) {
                if (config != null) {
                    responseRandomKey = config.getDomainsKey();
                }
            }
            if (!TextUtils.isEmpty(domains) && !TextUtils.isEmpty(orgId) && !TextUtils.isEmpty(responseRandomKey)) {
                String domainsKey = orgId + "." + responseRandomKey;
                if (!TextUtils.isEmpty(domainsKey)) {
                    String json = SignUtils.decryptDataWithAES(domainsKey, domains);
                    BackupDomainList backupDomains = JsonConvertor.getInstance().fromJson(json, BackupDomainList.class);

                    BackupDomainManager.getInstance().saveBackupDomainList(backupDomains);
                    DebugLog.e("domainList: " + json);
                }
            }
        } catch (Exception e) {
            e.printStackTrace();

        }
    }

    /**
     * 获取orgId
     * @return
     */
    public String getOrgId(){
        return orgId;
    }

    /**
     * 加载币币 token进Map
     * @param response
     */
    private void loadTokenItemToMap(NewCoinPairListBean response) {
        if (response != null) {
            if (response.token != null) {
                HashMap<String, QuoteTokensBean.TokenItem> newTokenMap = new HashMap<>();
                for (QuoteTokensBean.TokenItem tokenItem : response.token) {
                    newTokenMap.put(tokenItem.getTokenId(),tokenItem);
                }
                tokenMap = newTokenMap;
            }
        }
    }

    /**
     * 获取token信息
     * @param tokenId
     * @return
     */
    public QuoteTokensBean.TokenItem getTokenItemByTokenId(String tokenId){
        return tokenMap.get(tokenId);
    }

    /**
     * 获取token 链路类型
     * @param tokenId
     * @return
     */
    public List<ChainType> getTokenChainTypesByTokenId(String tokenId){
        QuoteTokensBean.TokenItem tokenItem = getTokenItemByTokenId(tokenId);
        if (tokenItem != null) {
            List<ChainType> chainTypes = tokenItem.getChainTypes();
            return chainTypes;
        }
        return null;
    }

    /**
     * 加载币对列表到内存中，方便各个地方使用
     *
     * @param response
     */
    private void loadSymbolsToMap(NewCoinPairListBean response) {
        if (response != null) {
            //币币币对
            List<CoinPairBean> bbSymbolsList = response.symbol;
            if (bbSymbolsList != null && bbSymbolsList.size() > 0) {
//                symbolMap.clear();
//                symbolDigitMap.clear();
                HashMap<String, CoinPairBean> newSymbolMap = new HashMap<>();
                HashMap<String, Integer> newSymbolDigitMap = new HashMap<>();

                for (CoinPairBean data : bbSymbolsList) {
                    data.setCoinType(COIN_TYPE.COIN_TYPE_BB.getCoinType());
                    String basePrecision = data.getBasePrecision();
//                    basePrecision = "10";
                    if (!TextUtils.isEmpty(basePrecision)) {
                        int baseDigit = NumberUtils.calNumerCount(null, basePrecision);
                        data.setBaseDigit(baseDigit);
                        newSymbolDigitMap.put(data.getSymbolId()+data.getBaseTokenId(),baseDigit);
                    }
                    String quotePrecision = data.getQuotePrecision();
                    if (!TextUtils.isEmpty(quotePrecision)) {
                        int quoteDigit = NumberUtils.calNumerCount(null, quotePrecision);
                        data.setAmountDigit(quoteDigit);
                        newSymbolDigitMap.put("amount-"+data.getSymbolId()+data.getQuoteTokenId(),quoteDigit);
                    }
                    String minPricePrecision = data.getMinPricePrecision();
                    if (!TextUtils.isEmpty(minPricePrecision)) {
                        int priceDigit = NumberUtils.calNumerCount(null, minPricePrecision);
                        data.setPriceDigit(priceDigit);
                        newSymbolDigitMap.put(data.getSymbolId()+data.getQuoteTokenId(),priceDigit);
                    }

                    String symbolId = data.getSymbolId();
                    newSymbolMap.put(symbolId, data);
                }
                symbolDigitMap = newSymbolDigitMap;
                symbolMap = newSymbolMap;
            }

            //期货币对
            List<CoinPairBean> futuresSymbolList = response.futuresSymbol;
            if (futuresSymbolList != null && futuresSymbolList.size() > 0) {
                HashMap<String, CoinPairBean> newFuturesSymbolMap = new HashMap<>();
                HashMap<String, Integer> newFuturesSymbolDigitMap = new HashMap<>();
                for (CoinPairBean data : futuresSymbolList) {
                    data.setCoinType(COIN_TYPE.COIN_TYPE_PERPETUAL_CONTRACT.getCoinType());
                    String basePrecision = data.getBasePrecision();
                    if (!TextUtils.isEmpty(basePrecision)) {
                        int baseDigit = NumberUtils.calNumerCount(null, basePrecision);
                        data.setBaseDigit(baseDigit);
                        newFuturesSymbolDigitMap.put(data.getSymbolId()+data.getBaseTokenId(),baseDigit);
                    }
                    String quotePrecision = data.getQuotePrecision();
                    if (!TextUtils.isEmpty(quotePrecision)) {
                        int quoteDigit = NumberUtils.calNumerCount(null, quotePrecision);
                        data.setAmountDigit(quoteDigit);
                        newFuturesSymbolDigitMap.put("amount-"+data.getSymbolId()+data.getQuoteTokenId(),quoteDigit);
                    }
                    String minPricePrecision = data.getMinPricePrecision();
                    if (!TextUtils.isEmpty(minPricePrecision)) {
                        int priceDigit = NumberUtils.calNumerCount(null, minPricePrecision);
                        data.setPriceDigit(priceDigit);
                        newFuturesSymbolDigitMap.put(data.getSymbolId()+data.getQuoteTokenId(),priceDigit);
                    }

                    String symbolId = data.getSymbolId();
                    newFuturesSymbolMap.put(symbolId, data);
                }
                futuresSymbolMap = newFuturesSymbolMap;
                futuresSymbolDigitMap = newFuturesSymbolDigitMap;
            }

            //期权币对分类：主板 创新板
            List<OptionCategoryBean> categoryList = response.optionUnderlying;
            if (categoryList != null && categoryList.size()>0) {
                HashMap<String, OptionCategoryBean> newOptionCategoryMap = new HashMap<>();
                for (OptionCategoryBean optionCategoryBean : categoryList) {
                    newOptionCategoryMap.put(optionCategoryBean.getId(),optionCategoryBean);
                }
                optionCategoryMap = newOptionCategoryMap;
            }

            //期权币对Symbol
            List<CoinPairBean> optionDatas = response.optionSymbol;
            if (optionDatas != null && optionDatas.size() > 0) {

                HashMap<String, CoinPairBean> newOptionSymbolMap = new HashMap<>();
                HashMap<String, Integer> newOptionSymbolDigitMap = new HashMap<>();
                for (CoinPairBean data : optionDatas) {
                    data.setCoinType(COIN_TYPE.COIN_TYPE_OPTION.getCoinType());
                    String basePrecision = data.getBasePrecision();
                    if (!TextUtils.isEmpty(basePrecision)) {
                        int baseDigit = NumberUtils.calNumerCount(null, basePrecision);
                        data.setBaseDigit(baseDigit);
                        newOptionSymbolDigitMap.put(data.getSymbolId()+data.getBaseTokenId(),baseDigit);
                    }
                    String quotePrecision = data.getQuotePrecision();
                    if (!TextUtils.isEmpty(quotePrecision)) {
                        int quoteDigit = NumberUtils.calNumerCount(null, quotePrecision);
                        data.setAmountDigit(quoteDigit);
                        newOptionSymbolDigitMap.put("amount-"+data.getSymbolId()+data.getQuoteTokenId(),quoteDigit);
                    }
                    String minPricePrecision = data.getMinPricePrecision();
                    if (!TextUtils.isEmpty(minPricePrecision)) {
                        int priceDigit = NumberUtils.calNumerCount(null, minPricePrecision);
                        data.setPriceDigit(priceDigit);
                        newOptionSymbolDigitMap.put(data.getSymbolId()+data.getQuoteTokenId(),priceDigit);
                    }

                    String symbolId = data.getSymbolId();
                    newOptionSymbolMap.put(symbolId, data);
                }
                optionSymbolDigitMap = newOptionSymbolDigitMap;
                optionSymbolMap = newOptionSymbolMap;
            }
        }
    }

    /**
     * 获取币币symbols
     * @return
     */
    public HashMap<String,CoinPairBean> getBBSymbolMap(){
        return symbolMap;
    }

    /**
     * 获取合约symbols
     * @return
     */
    public HashMap<String,CoinPairBean> getContractSymbolMap(){
        return futuresSymbolMap;
    }

    /**
     * 获取期权symbols
     * @return
     */
    public HashMap<String,CoinPairBean> getOptionSymbolMap(){
        return optionSymbolMap;
    }

    /**
     * 获取币对实体信息
     * @param id
     * @return
     */
    public CoinPairBean getSymbolInfoById(String id){
        if (symbolMap.containsKey(id)) {
            return symbolMap.get(id);
        }
        else if(optionSymbolMap.containsKey(id)) {
            return optionSymbolMap.get(id);
        }else if(futuresSymbolMap.containsKey(id)){
            return futuresSymbolMap.get(id);
        }else{
            return null;
        }
    }

    /**
     * 获取期货币对实体信息
     * @param id
     * @return
     */
    public CoinPairBean getFuturesSymbolInfoById(String id){
        if(futuresSymbolMap.containsKey(id)){
            return futuresSymbolMap.get(id);
        }else{
            return null;
        }
    }

    public CoinPairBean getSymbolByToken(String token){
        if(symbolMap != null) {
            for (Map.Entry<String, CoinPairBean> entry : symbolMap.entrySet()) {
                if(entry.getKey().startsWith(token))
                    return entry.getValue();
            }
            for (Map.Entry<String, CoinPairBean> entry : symbolMap.entrySet()) {

                if(entry.getKey().contains(token))
                    return entry.getValue();
            }
        }
//        if(optionSymbolMap != null) {
//            for (Map.Entry<String, CoinPairBean> entry : optionSymbolMap.entrySet()) {
//                if(entry.getKey().startsWith(token))
//                    return entry.getValue();
//            }
//            for (Map.Entry<String, CoinPairBean> entry : optionSymbolMap.entrySet()) {
//                if(entry.getKey().contains(token))
//                    return entry.getValue();
//            }
//        }
        return null;
    }

    /**
     * 根据 symbolId + tokenId 获取token小数位数
     * @param id
     * @return 如果token列表里没有查询到，则返回默认值
     */
    public int getAmountDigitBySymbolIdAndTokenId(String id){
        if (!TextUtils.isEmpty(id)&&symbolDigitMap.containsKey(id)) {
            return symbolDigitMap.get("amount-"+id);
        }else if (!TextUtils.isEmpty(id)&&optionSymbolDigitMap.containsKey(id)) {
            return optionSymbolDigitMap.get("amount-"+id);
        }else if (!TextUtils.isEmpty(id)&&futuresSymbolDigitMap.containsKey(id)) {
            return futuresSymbolDigitMap.get("amount-"+id);
        }else{
            return AppData.Config.DIGIT_DEFAULT_VALUE;
        }
    }

    /**
     * 根据 symbolId + tokenId 获取token小数位数
     * @param id
     * @return 如果token列表里没有查询到，则返回默认值
     */
    public int getTokenDigitBySymbolIdAndTokenId(String id){
        if (!TextUtils.isEmpty(id)&&symbolDigitMap.containsKey(id)) {
            return symbolDigitMap.get(id);
        }else if (!TextUtils.isEmpty(id)&&optionSymbolDigitMap.containsKey(id)) {
            return optionSymbolDigitMap.get(id);
        }else if (!TextUtils.isEmpty(id)&&futuresSymbolDigitMap.containsKey(id)) {
            return futuresSymbolDigitMap.get(id);
        }
        else{
            return AppData.Config.DIGIT_DEFAULT_VALUE;
        }
    }

    public boolean isFavorite(CoinPairBean coinPairBean){
        if (coinPairBean != null) {
            if (favoritesMap != null) {
                String key = coinPairBean.getExchangeId() + "." + coinPairBean.getSymbolId();
                return favoritesMap.containsKey(key);
            }
        }
        return false;
    }

    public void cancelLocalFavorite(CoinPairBean cancelItems){
        if (cancelItems != null) {
            CoinPairBean bbCoin = symbolMap.get(cancelItems.getSymbolId());
            bbCoin.setFavorite(false);
            favoritesMap.remove(cancelItems.getExchangeId() + "." + cancelItems.getSymbolId());
        }
    }

    public void cancelLocalFavorite(List<CoinPairBean> localFavoriteList){
        if (symbolMap != null) {
            for (CoinPairBean coinPairBean : localFavoriteList) {
                CoinPairBean bbCoin = symbolMap.get(coinPairBean.getSymbolId());
                bbCoin.setFavorite(false);
            }
        }
    }

    public void setLocalFavoriteMap(List<CoinPairBean> localFavoriteList) {
        if (localFavoriteList != null) {
            Map<String,FavoriteListResponse.FavoriteBean> localFavoritesMap = new HashMap<>();
            for (CoinPairBean coinPairBean : localFavoriteList) {
                if (coinPairBean != null) {
                    FavoriteListResponse.FavoriteBean favoriteBean = new FavoriteListResponse.FavoriteBean();
                    favoriteBean.setExchangeId(coinPairBean.getExchangeId());
                    favoriteBean.setSymbolId(coinPairBean.getSymbolId());
                    localFavoritesMap.put(coinPairBean.getExchangeId()+"."+coinPairBean.getSymbolId(),favoriteBean);
                }
            }

            //TODO 本地收藏
            favoritesMap = localFavoritesMap;//登录信息，重置自选MAP

            if(mNewCoinPairListBean !=null && mNewCoinPairListBean.symbol!=null){
                List<CoinPairBean> list = mNewCoinPairListBean.symbol;
                if (list != null && favoritesMap.size()>0) {
                    DebugLog.e("ZIXUAN","=============================");
                    for (CoinPairBean datum : list) {
                        String key = datum.getExchangeId() + "." + datum.getSymbolId();
                        if (favoritesMap.containsKey(key)) {
                            datum.setFavorite(true);
                            DebugLog.e("ZIXUAN","== "+key);
                        }
                    }
                }
            }
        }
    }

    /**
     * 获取 币币-自选
     */
    public void getFavorites(){
        if (!UserInfo.isLogin()) {
           return;
        }
        PostParams params = BParamsBuilder.post()
                .url(Urls.API_FAVORITE_LIST_URL)
                .build();
        HttpUtils.getInstance().request(params,FavoriteListResponse.class,new SimpleResponseListener<FavoriteListResponse>(){
            @Override
            public void onFinish() {
                super.onFinish();
            }

            @Override
            public void onSuccess(FavoriteListResponse data) {
                super.onSuccess(data);
                if (CodeUtils.isSuccess(data, false)) {

                    NetWorkApiManager.getTradeInstance();//启动tradesocket 需要登录成功

                    List<FavoriteListResponse.FavoriteBean> favoriteBeanList = data.getArray();
                    Map<String,FavoriteListResponse.FavoriteBean> userLoginFavoritesMap = new HashMap<>();
                    if (favoriteBeanList != null) {
                        for (FavoriteListResponse.FavoriteBean favoriteBean : favoriteBeanList) {
                            userLoginFavoritesMap.put(favoriteBean.getExchangeId()+"."+favoriteBean.getSymbolId(),favoriteBean);
                        }
                    }

                    //TODO 暂不同步服务端收藏
//                    favoritesMap = userLoginFavoritesMap;//登录信息，重置自选MAP
//
//                    if(mNewCoinPairListBean !=null && mNewCoinPairListBean.symbol!=null){
//                        List<CoinPairBean> list = mNewCoinPairListBean.symbol;
//                        if (list != null && favoritesMap.size()>0) {
//                            DebugLog.e("ZIXUAN","=============================");
//                            for (CoinPairBean datum : list) {
//                                String key = datum.getExchangeId() + "." + datum.getSymbolId();
//                                if (favoritesMap.containsKey(key)) {
//                                    datum.setFavorite(true);
//                                    DebugLog.e("ZIXUAN","== "+key);
//                                }
//                            }
//                        }
//                    }

                    if(mObserverList != null && mObserverList.size() > 0){
                        for (LoginstatusChange observer: mObserverList) {
                            observer.onFavriateChange();
                        }
                    }
                }
            }

            @Override
            public void onError(Throwable error) {
                super.onError(error);
            }
        });
    }

    /**
     * 登录用户自选数据map
     * @return
     */
    public Map<String, FavoriteListResponse.FavoriteBean> getFavoritesMap(){
        return favoritesMap;
    }

    /**
     * 获取 默认交易币种（币币交易）
     * @return
     */
    public CoinPairBean getDefaultTradeCoinPair(){
        return mDefaultBBTradeCoinPair;
    }

    /**
     * 获取 默认交易币种（期权交易）
     * @return
     */
    public CoinPairBean getDefaultOptionTradeCoinPair(){
        return mDefaultOptionTradeCoinPair;
    }

    /**
     * 获取 默认交易币种（期货交易）
     * @return
     */
    public CoinPairBean getDefaultFuturesTradeCoinPair(){
        return mDefaultFuturesTradeCoinPair;
    }

    /**
     * 获取期货-作价token
     * @return
     */
    public List<String> getFuturesCoinToken(){
        if(mNewCoinPairListBean != null)
            return mNewCoinPairListBean.futuresCoinToken;
        else
            return null;
    }

    /**
     * 获取期权-作价token
     * @return
     */
    public List<String> getOptionCoinToken(){
        if(mNewCoinPairListBean != null)
            return mNewCoinPairListBean.optionCoinToken;
        else
            return null;
    }

    /**
     * 获取体验币-作价token
     * @return
     */
    public List<String> getExploreToken(){
        if(mNewCoinPairListBean != null)
            return mNewCoinPairListBean.exploreToken;
        else
            return null;
    }

    //体验币
    HashMap<String, String> exploreTokenMap = new HashMap<>();
    public HashMap<String, String> getExploreTokenMap(){
        return exploreTokenMap;
    }

    public HashMap<String, String> putExploreTokenIntoMap(String tokenName,String tokenId){
        exploreTokenMap.put(tokenName,tokenId);
        return exploreTokenMap;
    }

    /**
     * 获取期权所有指数tokens BTCUSDT,ETHUSDT
     * @return
     */
    public String getAllIndexTokensOfOptions(){
        StringBuffer stringBuffer = new StringBuffer();
        if (mNewCoinPairListBean != null && mNewCoinPairListBean.optionSymbol != null) {
            for (CoinPairBean coinPairBean : mNewCoinPairListBean.optionSymbol) {
                if(coinPairBean.baseTokenOption != null) {
                    String indexToken = coinPairBean.baseTokenOption.indexToken;
                    if(!stringBuffer.toString().contains(indexToken)) {
                        if (stringBuffer.toString().length() > 0) {
                            stringBuffer.append("," + indexToken);
                        } else {
                            stringBuffer.append(indexToken);
                        }
                    }
                }
            }
        }
        return stringBuffer.toString();
    }

    /**
     * 获取合约期货所有指数tokens BTCUSDT,ETHUSDT
     * @return
     */
    public String getAllIndexTokensOfFutures(){
        StringBuffer stringBuffer = new StringBuffer();
        if (mNewCoinPairListBean != null && mNewCoinPairListBean.futuresSymbol != null) {
            for (CoinPairBean coinPairBean : mNewCoinPairListBean.futuresSymbol) {
                if(coinPairBean.baseTokenFutures != null) {
                    String displayIndexToken = coinPairBean.baseTokenFutures.getDisplayIndexToken();
                    if(!stringBuffer.toString().contains(displayIndexToken)) {
                        if (stringBuffer.toString().length() > 0) {
                            stringBuffer.append("," + displayIndexToken);
                        } else {
                            stringBuffer.append(displayIndexToken);
                        }
                    }
                }
            }
        }
        return stringBuffer.toString();
    }

    protected String getSymbolsListStr(List<CoinPairBean> list) {
        StringBuffer stringBuffer = new StringBuffer();
        if (list != null && list.size() > 0) {
            for (CoinPairBean coinPairBean : list) {
                if (coinPairBean != null) {
                    String symbol = coinPairBean.getExchangeId() + "." + coinPairBean.getSymbolId();
                    if (stringBuffer.toString().length() > 0) {
                        stringBuffer.append("," + symbol);
                    } else {
                        stringBuffer.append(symbol);
                    }
                }
            }

        }
        return stringBuffer.toString();
    }

    protected String getTokenListStr(List<QuoteTokensBean.TokenItem> list) {

        StringBuffer stringBuffer = new StringBuffer();
        if (list != null && list.size() > 0) {
            for (QuoteTokensBean.TokenItem tokenItem : list) {

                String tokenId = tokenItem.getTokenId();
                if (!tokenId.equals(AppData.KEY_FAVORITE)) {
                    if (stringBuffer.toString().length() > 0) {
                        stringBuffer.append("," + tokenId);
                    } else {
                        stringBuffer.append(tokenId);
                    }
                }
            }

        }
        return stringBuffer.toString();
    }

    /**
     * 获取所有tokens 拼接参数
     * @return
     */
    protected String getTokenListStr() {
        List<QuoteTokensBean.TokenItem> tokenList = getTokenList();
        if (tokenList != null&&tokenList.size()>0) {
            return getTokenListStr(tokenList);
        }else{
            return "";
        }
    }

    /**
     * 获取所有tokens 拼接参数
     * @return
     */
    protected String getQuoteTokenListStr() {

        List<QuoteTokensBean.TokenItem> tokenList = getQuoteTokenList();
        if (tokenList != null&&tokenList.size()>0) {
            return getTokenListStr(tokenList);
        }else{
            return "";
        }
    }

    /**
     * 合约帮助地址
     * @return
     */
    public String getContractHelpUrl(){
        if (mNewCoinPairListBean != null) {
            return mNewCoinPairListBean.contractHelpUrl;
        }
        return "";
    }
}
